<?php
// +-------------------------------------------------------------------------------
// | DingZone [ A Rapid Development Framework For Dingtalk ]
// +-------------------------------------------------------------------------------
// | 企业相关回调Controller v1.0
// |
// | Copyright (c) 2014-2018 http://www.heimalanshi.com All rights reserved.
// | Author : Jie
// | Date : 2018-08-09
// +-------------------------------------------------------------------------------

namespace app\core\controller\enterprise;

use app\core\controller\CoreBaseController;
use app\core\model\Enterprise;
use app\core\service\DingSyncService;
use common\Encryption;
use ding\ApiHelper;
use ding\model\CallbackTagEnum;
use ding\util\DingtalkCrypt;
use ding\util\ErrorCode;

class CallbackController extends CoreBaseController {
    protected function checkLogin() {
        return "no-need";
    }

    /**
     * 事件回调
     *
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function index() {
        $data = $this->request->getInput();
        $this->_d($data);
        $data = json_decode($data, true);

        $eid = input("get.eid");
        $enterprise = Enterprise::get($eid);
        $this->_d($enterprise);

        if (empty($enterprise) || empty($enterprise['callback'])) {
            $this->_log("can not find enterprise, eid = " . $eid, "callback");
            exit;
        }
        $callback = json_decode($enterprise['callback'], true);
        $key = DEFAULT_DECRYPT_KEY;
        $corpid = Encryption::decrypt($enterprise['corpid'], $key);;
        $token = fetch($callback, "token");
        $aesKey = fetch($callback, "aesKey");
        if (empty($corpid) || empty($token) || empty($aesKey)) {
            $this->_log("corpid or token or aesKey is empty, eid = " . $eid, "callback");
            exit;
        }

        $signature = input("get.signature");
        $timestamp = input("get.timestamp");
        $nonce = input("get.nonce");
        $encrypt = $data['encrypt'];

        $crypt = new DingtalkCrypt($token, $aesKey, $corpid);
        $decryptMsg = "";
        $result = $crypt->decryptMsg($signature, $timestamp, $nonce, $encrypt, $decryptMsg);
        if ($result != ErrorCode::$OK) {
            $this->_log("内容解密失败。errorcode = " . $result . " encrypt = " . $encrypt, "callback");
        }
        $this->_d($result);
        $this->_d($decryptMsg);

        //处理回调消息
        $this->_handleCallback($enterprise, $decryptMsg);

        $encryptMsg = "";
        $crypt->encryptMsg("success", $timestamp, $nonce, $encryptMsg);
        $this->_d($encryptMsg);
        die($encryptMsg);
    }

    /**
     * 处理消息回调
     *
     * @param $enterprise
     * @param $callbackMsg
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    private function _handleCallback($enterprise, $callbackMsg) {
        if (is_string($callbackMsg)) {
            $callbackMsg = json_decode($callbackMsg, true);
        }
        $eventType = $callbackMsg['EventType'];

        switch ($eventType) {
            case CallbackTagEnum::BPMS_INSTANCE_CHANGE:
                //审批实例状态变化
                $this->_handleBpmsInstanceChange($enterprise, $callbackMsg);
                break;
            case CallbackTagEnum::BPMS_TASK_CHANGE:
                //审批任务节点变化
                $this->_handleBpmsTaskChange($enterprise, $callbackMsg);
                break;
        }
    }

    /**
     * 审批实例状态变化
     *
     * @param $enterprise
     * @param $callbackMsg
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    private function _handleBpmsInstanceChange($enterprise, $callbackMsg) {
        $bizCategoryId = fetch($callbackMsg, "bizCategoryId", "");
        $url = fetch($callbackMsg, 'url', "");
        $processCode = fetch($callbackMsg, 'processCode', "");
        $processInstanceId = fetch($callbackMsg, 'processInstanceId', "");

        $apiHelper = new ApiHelper($enterprise, null);
        DingSyncService::syncBpmsInstance($enterprise, $apiHelper, $processInstanceId, [
            'biz_category_id' => $bizCategoryId,
            'url' => $url,
            'process_code' => $processCode
        ]);
    }

    /**
     * 审批任务状态变化
     *
     * @param $enterprise
     * @param $callbackMsg
     */
    private function _handleBpmsTaskChange($enterprise, $callbackMsg) {
        $bizCategoryId = fetch($callbackMsg, "bizCategoryId", "");
        $processCode = fetch($callbackMsg, 'processCode', "");
        $processInstanceId = fetch($callbackMsg, 'processInstanceId', "");

        $apiHelper = new ApiHelper($enterprise, null);
        DingSyncService::syncBpmsInstance($enterprise, $apiHelper, $processInstanceId, [
            'biz_category_id' => $bizCategoryId,
            'process_code' => $processCode
        ]);
    }
}
